<?php
/*
 * @ https://EasyToYou.eu - IonCube v11 Decoder Online
 * @ PHP 7.2 & 7.3
 * @ Decoder version: 1.1.6
 * @ Release: 10/08/2022
 */

// Decoded file for php version 71.
namespace Qcloud\Cos;

class Copy
{
    private $client;
    private $source;
    private $options;
    private $partSize;
    private $size;
    const MIN_PART_SIZE = 5242880;
    const MAX_PART_SIZE = 1073741824;
    const MAX_PARTS = 10000;
    public function __construct($client, $contentlength, $source, $minPartSize, $options = [])
    {
        $this->client = $client;
        $this->source = $source;
        $this->options = $options;
        $this->size = $contentlength;
        $this->partSize = $this->calculatePartSize($minPartSize);
        $this->concurrency = isset($options["concurrency"]) ? $options["concurrency"] : 10;
        $this->retry = isset($options["retry"]) ? $options["retry"] : 5;
    }
    public function copy()
    {
        $uploadId = $this->initiateMultipartUpload();
        $i = 0;
        while ($i < 5) {
            $rt = $this->uploadParts($uploadId);
            if($rt == 0) {
                break;
            }
            sleep(1 << $i);
            $i += 1;
        }
        return $this->client->completeMultipartUpload(["Bucket" => $this->options["Bucket"], "Key" => $this->options["Key"], "UploadId" => $uploadId, "Parts" => $this->parts]);
    }
    public function uploadParts($uploadId)
    {
        $commands = [];
        $offset = 0;
        $partNumber = 1;
        $partSize = $this->partSize;
        $finishedNum = 0;
        $this->parts = [];
        while (true) {
            if($this->size <= $offset + $partSize) {
                $partSize = $this->size - $offset;
            }
            $params = ["Bucket" => $this->options["Bucket"], "Key" => $this->options["Key"], "UploadId" => $uploadId, "PartNumber" => $partNumber, "CopySource" => $this->source, "CopySourceRange" => "bytes=" . (string) $offset . "-" . (string) ($offset + $partSize - 1)];
            if(!isset($parts[$partNumber])) {
                $commands[] = $this->client->getCommand("UploadPartCopy", $params);
            }
            if($partNumber % $this->concurrency == 0) {
                $this->client->execute($commands);
                $commands = [];
            }
            $partNumber++;
            $offset += $partSize;
            if($this->size == $offset) {
                break;
            }
        }
        if(!empty($commands)) {
            $this->client->execute($commands);
        }
        try {
            $marker = 0;
            $finishedNum = 1;
            while (true) {
                $rt = $this->client->listParts(["Bucket" => $this->options["Bucket"], "Key" => $this->options["Key"], "PartNumberMarker" => $marker, "MaxParts" => 1000, "UploadId" => $uploadId]);
                if(!empty($rt["Parts"])) {
                    foreach ($rt["Parts"] as $part) {
                        $part = ["PartNumber" => $finishedNum, "ETag" => $part["ETag"]];
                        $this->parts[$finishedNum] = $part;
                        $finishedNum++;
                    }
                }
                $marker = $rt["NextPartNumberMarker"];
                if(!$rt["IsTruncated"]) {
                }
            }
        } catch (\Exception $e) {
            echo $e;
        }
        if($finishedNum == $partNumber) {
            return 0;
        }
        return -1;
    }
    private function calculatePartSize($minPartSize)
    {
        $partSize = intval(ceil($this->size / self::MAX_PARTS));
        $partSize = max($minPartSize, $partSize);
        $partSize = min($partSize, self::MAX_PART_SIZE);
        $partSize = max($partSize, self::MIN_PART_SIZE);
        return $partSize;
    }
    private function initiateMultipartUpload()
    {
        $result = $this->client->createMultipartUpload($this->options);
        return $result["UploadId"];
    }
}
function partUploadCopy($client, $params)
{
    $rt = $client->uploadPartCopy($params);
    $rt["PartNumber"] = $params["PartNumber"];
    return $rt;
}

?>